package com.gitee.wsl.logger

//package me.lwb.logger

/**
 * 日志输出
 */
fun interface LogPrinter {
    /**
     * 输出日志
     */
    fun log(
        level: LogLevel,
        tag: String,
        messageAny: Any?,
        throwable: Throwable?
    )

    companion object{
        val DEFAULT: LogPrinter = object : LogPrinter {
            override fun log(level: LogLevel, tag: String, messageAny: Any?, throwable: Throwable?) {
                println(tag+": $messageAny"+" $throwable")
            }
        }
    }
}

/**
 * LogPrinter拓展
 */
/**
 * 拦截器
 * logPrinter 被拦截对象
 */
typealias LogPrinterInterceptor = (logPrinter: LogPrinter, level:LogLevel, tag: String, messageAny: Any?, throwable: Throwable?) -> Unit

inline fun LogPrinter.intercept(crossinline interceptor: LogPrinterInterceptor) =
    LogPrinter { level, tag, messageAny, throwable ->
        interceptor(this, level, tag, messageAny, throwable)
    }


/**
 * 添加额外的日志记录器
 */
fun LogPrinter.logAlso(other: LogPrinter) =
    intercept { logPrinter, level, tag, messageAny, throwable ->
        logPrinter.log(level, tag, messageAny, throwable)
        other.log(level, tag, messageAny, throwable)
    }

operator fun LogPrinter.plus(other: LogPrinter) = this.logAlso(other)

operator fun Logger.plusAssign(other: LogPrinter){
    logPrinter = logPrinter.logAlso(other)
}

/**
 * 日志过滤
 */
fun LogPrinter.filter(
    predicate: (
        level: LogLevel,
        tag: String,
        messageAny: Any?,
        throwable: Throwable?
    ) -> Boolean
) = intercept { logPrinter, level, tag, messageAny, throwable ->
        if (predicate(level, tag, messageAny, throwable)) {
            logPrinter.log(level, tag, messageAny, throwable)
        }
    }

/**
 * 日志过滤
 */
fun LogPrinter.filterLevel(minLevel: LogLevel) = filter { level, _, _, _ -> level >= minLevel }

/**
 * 日志过滤
 */
fun LogPrinter.filterTag(tagWhitelist: List<String> = emptyList(),
                         tagBlacklist: List<String> = emptyList()
   ) = filter { level, tag, _, _ ->
       if(tagWhitelist.isNotEmpty() && !tagWhitelist.contains(tag))
           return@filter false
       if(tagBlacklist.isNotEmpty() &&!tagBlacklist.contains(tag))
           return@filter false
       return@filter true
   }

